                
;*******************************************************}
;                                                       }
;       Yalgol/02 run-time library (Win32)              }
;       Startup code                                    }
;                                                       }
;       Written by Y [18-08-02] <yallie@mail.ru>        }
;       Based on Why32 and Yalgol/01 startup code       }
;         written by Y [07-04-00], [06-04-02]           }
;                                                       }
;       Copyright (c) 2000-2003 YALLIE, Inc.            }
;       All Rights Reserved                             }
;                                                       }
;*******************************************************}

; $Id: y02run.asm,v 1.7 2003/06/29 15:53:37 Y Exp $

TITLE Yalgol/02 run-time library startup code (Win32)

.386
.MODEL FLAT, C

;DEBUG_MEMORY = 1

_DATA           SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA           ENDS
_TEXT           SEGMENT DWORD USE32 PUBLIC 'CODE'
_TEXT           ENDS
DGROUP          GROUP _DATA

;*******************************************************
_DATA           SEGMENT DWORD USE32 PUBLIC 'DATA'
                ORG 0
;NULL           DD 0
Banner          DB 10, 'Yalgol/02 run-time library (Win32)', 10
Copyright       DB 'Copyright (c) 1999-2003 YALLIE, Inc.', 10
                DB 'All Rights Reserved', 10, 0

IFDEF IMNGR
MemoryHandle    DD 0
LastAddress     DD 0, 0
ENDIF
                DB 10, 10

_DATA           ENDS

;*******************************************************
_TEXT           SEGMENT DWORD USE32 PUBLIC 'CODE'

PUBLIC          WinMain, L_MALLOC, L_FREE
EXTRN           Main$u$: NEAR

; program entry point

WinMain         PROC

        ; initialize simple incremental memory manager 
        ; (required by compiler executed under 32rtm extender)
        IFDEF IMNGR
                PUSH    dword ptr IMNGR * 1024
                PUSH    dword ptr 40h   ; GMEM_ZEROINIT
                CALL    GlobalAlloc
                MOV     [MemoryHandle], EAX
                PUSH    EAX
                CALL    GlobalLock
                MOV     [LastAddress], EAX
        ENDIF

        ; call main code
                CALL    Main$u$

        ; deinitialize incremental memory manager 
        IFDEF IMNGR
                MOV     EAX, [MemoryHandle]
                PUSH    EAX
                CALL    GlobalFree
        ENDIF

        ; exit to OS
                PUSH    dword ptr 0
                CALL    ExitProcess
                RET
                ENDP

; memory allocation
; -> size needed
; <- block address

L_MALLOC        PROC

        ; define DEBUG_MEMORY flag to track memory management
        IFDEF DEBUG_MEMORY

        .DATA
        cCounter DD 0
        cMalloc DB "malloc: ", 0
        .CODE
        EXTRN   Put$u$$s: NEAR, Puts$u$$i: NEAR
                PUSHAD
                LEA     EAX, cMalloc
                PUSH    EAX
                CALL    Put$u$$s
                ADD     ESP, 4
                MOV     EAX, [cCounter]
                INC     EAX
                MOV     [cCounter], EAX
                PUSH    EAX
                CALL    Puts$u$$i
                ADD     ESP, 4
                POPAD
        ENDIF
                ; get argument (block size)
                MOV     EAX, [ESP + 4]

        IFDEF IMNGR
                ADD     EAX, 15
                AND     EAX, 0FFFFFFF0h ; align to paragraph
                MOV     EBX, [LastAddress]
                ADD     [LastAddress], EAX
                MOV     EAX, EBX
        ELSE
                ; use system memory manager
                PUSH    EAX
                PUSH    dword ptr 40h   ; GMEM_ZEROINIT
                CALL    GlobalAlloc
                PUSH    EAX
                CALL    GlobalLock
        ENDIF
                RETN    4
                ENDP

; memory deallocation
; -> block address

L_FREE          PROC

        ; define DEBUG_MEMORY flag to track memory management
        IFDEF DEBUG_MEMORY
        .DATA
        cFree   LABEL BYTE
                DB "free:   ", 0
        .CODE
                PUSHAD
                LEA     EAX, cFree
                PUSH    EAX
                CALL    Put$u$$s
                ADD     ESP, 4
                DEC     [cCounter]
                MOV     EAX, [cCounter]
                PUSH    EAX
                CALL    Puts$u$$i
                ADD     ESP, 4
                POPAD
        ENDIF
                ; get argument
                MOV     EAX, [ESP + 4]

        IFDEF IMNGR
                ; incremental memory manager ignores free request
        ELSE
                ; use system memory manager
                PUSH    EAX
                CALL    GlobalHandle
                PUSH    EAX
                CALL    GlobalFree
        ENDIF

                RETN    4
                ENDP

        EXTRN   $system: NEAR
                DD      $system

_TEXT           ENDS

.MODEL FLAT
EXTRN           GlobalAlloc: NEAR, GlobalFree: NEAR
EXTRN           GlobalHandle: NEAR, GlobalLock: NEAR
EXTRN           ExitProcess: NEAR

;*******************************************************
                END     WinMain

; $Log: y02run.asm,v $
; Revision 1.7  2003/06/29 15:53:37  Y
;   + a trick that ensures that "Translator version" string
;     from System unit is linked into executable
;
; Revision 1.6  2003/06/14 21:10:25  Y
;   * replaced symbol INCREMENTAL_MEMORY_MANAGER with IMNGR
;
; Revision 1.5  2003/02/22 22:14:14  Y
;   + INCREMENTAL_MEMORY_MANAGER for 32rtm extender
;
; Revision 1.4  2003/01/28 14:29:03  Y
;   * updated copyright
;
; Revision 1.3  2002/12/08 12:45:26  Y
;   * fixed old-style external names for DEBUG_MEMORY version
;
; Revision 1.2  2002/09/13 20:53:21  Y
;   * fixed up Banner string
;
; Revision 1.1  2002/09/12 21:36:15  Y
;   * imported into CVS
;
